NestJS의 Guard는 강력한 보안 및 인증 기능을 제공하며, 사용자 정의 Guard를 통해 액세스 제어를 구현할 수 있습니다. 이번 글에서는 “RolesGuard”라는 사용자 정의 Guard를 구현하면서 겪은 경험을 공유하고자 합니다.
1. RolesGuard 개발 시작하기
우선, “RolesGuard”를 개발하기 위해 새로운 Guard 클래스를 생성합니다. Guard 클래스는 @nestjs/common 모듈에서 제공하는 CanActivate 인터페이스를 구현해야 합니다. 이를 통해 Guard가 요청의 액세스를 허용 또는 거부하는 로직을 구현할 수 있습니다.
import { CanActivate, ExecutionContext, Injectable } from "@nestjs/common";
@Injectable()
export class RolesGuard implements CanActivate {
canActivate(context: ExecutionContext): boolean {
// 액세스 제어 로직을 구현합니다.
// ...
}
}
2. RolesGuard에 Role 기반 인가 로직 추가하기
이제 “RolesGuard”의 canActivate 메서드 내에서 Role 기반 인가 로직을 추가합니다. 여기서는 @Roles 데코레이터를 사용하여 엔드포인트에 필요한 Role 정보를 설정하고, @nestjs/core 모듈에서 제공하는 Reflector를 사용하여 해당 Role 정보를 추출합니다.
import { CanActivate, ExecutionContext, Injectable } from "@nestjs/common";
import { Reflector } from "@nestjs/core";
@Injectable()
export class RolesGuard implements CanActivate {
constructor(private reflector: Reflector) {}
canActivate(context: ExecutionContext): boolean {
const roles = this.reflector.get<string[]>("roles", context.getHandler());
if (!roles) {
return true; // @Roles 애노테이션이 없는 경우, 인가 통과
}
const request = context.switchToHttp().getRequest();
const user = request.user;
const userRoles = user.roles; // 사용자의 역할 정보 (예: user.roles)
const hasRole = userRoles.some((role) => roles.includes(role));
return hasRole; // 역할 확인 결과 반환
}
}
3. @Roles 데코레이터 생성하기
“RolesGuard”에서 Role 기반 인가를 수행하기 위해 @Roles 데코레이터를 생성합니다. 이 데코레이터는 엔드포인트 또는 컨트롤러에 필요한 Role 정보를 설정할 수 있도록 도와줍니다.
import { SetMetadata } from "@nestjs/common";
export const Roles = (...roles: string[]) => SetMetadata("roles", roles);
4. Guard 적용하기
마지막으로, “JwtAuthGuard”와 “RolesGuard”를 함께 사용하여 인증과 인가를 동시에 처리합니다. 엔드포인트 또는 컨트롤러에 @UseGuards(JwtAuthGuard, RolesGuard)를 추가하고, @Roles 데코레이터를 사용하여 필요한 Role 정보를 설정합니다.
import { Controller, Get, UseGuards } from "@nestjs/common";
import { JwtAuthGuard } from "./guards/jwt-auth.guard";
import { RolesGuard } from "./guards/roles.guard";
@Controller("example")
export class ExampleController {
@Get()
@UseGuards(JwtAuthGuard, RolesGuard)
someRoute() {
// ...
}
}
위의 예시에서 @UseGuards(JwtAuthGuard, RolesGuard)를 사용하여 "JwtAuthGuard"와 "RolesGuard"를 동시에 적용하고 있습니다. 이를 통해 요청이 들어올 때 먼저 "JwtAuthGuard"가 JWT 인증을 처리하고 사용자 정보를 추출한 후, "RolesGuard"가 역할 기반의 인가를 수행하게 됩니다.
“JwtAuthGuard”와 “RolesGuard”를 함께 사용하여 인증과 인가를 처리함으로써 NestJS 애플리케이션의 보안 수준을 높일 수 있습니다. 필요한 역할을 가진 사용자만이 허용된 리소스에 액세스할 수 있도록 보장합니다.
마무리
위의 단계를 따라가면 NestJS에서 Role-based 인가를 위한 사용자 정의 Guard를 개발할 수 있습니다. “RolesGuard”는 @Roles 데코레이터를 통해 설정된 Role 정보를 기반으로 인가를 수행하며, 엔드포인트 또는 컨트롤러에 @UseGuards(RolesGuard)를 추가하여 Guard를 적용할 수 있습니다.
Role 기반 인가를 구현함으로써 애플리케이션의 보안 수준을 높일 수 있으며, 필요한 역할을 가진 사용자만이 허용된 리소스에 액세스할 수 있게 됩니다.
이 글을 통해 NestJS에서 Role-based 인가를 구현하는 방법을 익히고, 애플리케이션의 보안을 강화할 수 있기를 바랍니다.